#include "InvestorAccount.h"
#include "../FacilityBaseLib/Container.h"
#include <algorithm>
#include <boost/make_shared.hpp>

#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>

#include <boost/serialization/base_object.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/map.hpp>
#include <fstream>

InvestorAccount::InvestorAccount(const std::string& Id)
	:Portfolio(Id), m_bFilterMyOrder(true)
{
	m_Investor = boost::make_shared<Investor>();
	m_SettlementInfo = boost::make_shared<SettlementInfo>();
	m_SettlementInfoConfirm = boost::make_shared<SettlementInfoConfirm>();

	//LOGDEBUG("加载保证金率和手续费...");
	LoadInstCommisionRate();
	LoadInstMarginRate();
	//LOGDEBUG("加载保证金率和手续费完成...");
}

InvestorAccount::InvestorAccount(const std::string& InvestorID,const std::string& BrokerID)
	:Portfolio(InvestorID), m_bFilterMyOrder(true)
{
	m_Investor = boost::make_shared<Investor>();
	m_SettlementInfo = boost::make_shared<SettlementInfo>();
	m_SettlementInfoConfirm = boost::make_shared<SettlementInfoConfirm>();
	m_Investor->InvestorID=InvestorID;
	m_Investor->BrokerID=BrokerID;

	//LOGDEBUG("加载保证金率和手续费...");
	LoadInstCommisionRate();
	LoadInstMarginRate();
	//LOGDEBUG("加载保证金率和手续费完成...");
}



InvestorAccount::~InvestorAccount(void)
{
}

void InvestorAccount::Update( const Investor& i)
{
	if (!m_Investor)
	{
		m_Investor = boost::make_shared<Investor>();
	}
	if (m_Investor->InvestorID == i.InvestorID && m_Investor->BrokerID == i.BrokerID)
	{
		*m_Investor = i;
	}
}


void InvestorAccount::Update( const SettlementInfo& si,bool bIsLast)
{
	if (!m_SettlementInfo)
	{
		m_SettlementInfo = boost::make_shared<SettlementInfo>(si);
	}
	else
	{
		*m_SettlementInfo = si;
	}
}

void InvestorAccount::Update( InvestorPositionDetailSPtr ipd,bool isUserLogin/*=false*/)
{
	if (!ipd)
	{
		return;
	}

	if (ipd->Volume==0)
	{
		return;
	}
	m_InvestorPositionDetail.push_back(ipd);

	//更新持仓;
	auto pdIter = std::find_if(m_MyPositions->begin(), m_MyPositions->end(),
	[ipd](InvestorPositionSPtr p){
		return p->InstrumentID == ipd->InstrumentID
			&& ipd->Direction == D_Buy? p->PosiDirection ==  PD_Long: p->PosiDirection== PD_Short;
	});
	if (pdIter != m_MyPositions->end())
	{
		//同一个合约方向相同;

	}
	else
	{
		//创建持仓;
		InvestorPositionSPtr p = boost::make_shared<InvestorPosition>();
		p->BrokerID = ipd->BrokerID;
		p->AbandonFrozen = 0;
		p->CashIn = 0;
		p->CloseAmount = ipd->CloseAmount;
		p->OpenPrice = ipd->OpenPrice;
		p->CloseProfitByDate = ipd->CloseProfitByDate;
		p->CloseProfitByTrade = ipd->CloseProfitByTrade;
		p->CloseVolume = ipd->CloseVolume;
		p->ExchangeID = ipd->ExchangeID;
	}
}

void InvestorAccount::Update( InvestorPositionCombineDetailSPtr ipcd,bool bIsUserLogin)
{
	if (m_InvestorPositionCombineDetail.empty())
	{
		m_InvestorPositionCombineDetail.push_back(ipcd);
	}
	else
	{
		for (std::size_t i=0;i<m_InvestorPositionCombineDetail.size();++i)
		{
			if (ipcd->InvestorID!=m_InvestorPositionCombineDetail[i]->InvestorID)
			{
				continue;
			}
			if ((ipcd->InstrumentID== m_InvestorPositionCombineDetail[i]->InstrumentID)
				&& (ipcd->Direction==m_InvestorPositionCombineDetail[i]->Direction))
			{
				//更新持仓;
				m_InvestorPositionCombineDetail[i]=ipcd;
			}
		}
	}
}

void InvestorAccount::Update(InvestorPositionSPtr ip)
{
	if (!ip)
	{
		return;
	}
	if (ip->Position == 0)
	{
		//总持仓为0则表示不用处理;
		return;
	}
	if (m_MyPositions->empty())
	{
		m_MyPositions->push_back(ip);
	}
	else
	{
		bool bFind = false;
		for (std::size_t i = 0; i < m_MyPositions->size(); ++i)
		{
			auto pPosition = (*m_MyPositions)[i];
			if (!pPosition)
			{
				continue;
			}
			if (ip->InvestorID != pPosition->InvestorID)
			{
				continue;
			}
			if ((ip->InstrumentID == pPosition->InstrumentID)
				&& (ip->PosiDirection == pPosition->PosiDirection)
				&& (ip->PositionDate == pPosition->PositionDate)
				)
			{
				//合并持仓方向相同的;
				pPosition->YdPosition += ip->YdPosition;
				pPosition->TodayPosition += ip->TodayPosition;
				int OrigPosition = pPosition->Position;
				pPosition->Position += ip->Position;
				pPosition->LongFrozen += ip->LongFrozen;
				pPosition->ShortFrozen += ip->ShortFrozen;
				pPosition->LongFrozenAmount += ip->LongFrozenAmount;
				pPosition->ShortFrozenAmount += ip->ShortFrozenAmount;
				pPosition->OpenVolume += ip->OpenVolume;
				pPosition->CloseVolume += ip->CloseVolume;
				pPosition->OpenAmount += ip->OpenAmount;
				pPosition->CloseAmount += ip->CloseAmount;
				pPosition->PositionCost += ip->PositionCost;
				pPosition->UseMargin += ip->UseMargin;
				pPosition->Commission += ip->Commission;
				pPosition->PositionProfit += ip->PositionProfit;
				pPosition->OpenCost += ip->OpenCost;
				bFind = true;
				break;
			}
		}
		if (!bFind)
		{
			m_MyPositions->push_back(ip);
		}
	}
}


void InvestorAccount::SafeUpdate( OrderSPtr o,bool bUserIsLogin /* = false */)
{
	boost::unique_lock<boost::mutex> lck(m_Mutex4Order);
	Portfolio::Update(o, !bUserIsLogin);
}

void InvestorAccount::SafeUpdate(TradeSPtr t, bool bUserIsLogin /* = false */)
{
	boost::unique_lock<boost::mutex> lck(m_Mutex4Trade);
	Portfolio::Update(t, !bUserIsLogin);
}

void InvestorAccount::SafeUpdate( const Investor& i)
{
	boost::unique_lock<boost::mutex> lck(m_Mutex4Investor);
	Update(i);
}

void InvestorAccount::SafeUpdate(TradingAccountSPtr ta)
{
	boost::unique_lock<boost::mutex> lck(m_Mutex4Account);
	*m_TradingAccount = *ta;
// 	if (!(m_TradingAccount->TradingDay.empty() || ta->TradingDay == m_TradingAccount->TradingDay))
// 	{
// 		m_TradingAccount = ta;
// 		m_TradingAccounts->push_back(ta);
// 	}
	if (m_TradingAccounts->empty())
	{
		m_TradingAccounts->push_back(ta);
	}
	else
	{
		if (m_TradingAccounts->back()->TradingDay == ta->TradingDay)
		{
			*m_TradingAccounts->back() = *ta;
		}
		else
		{
			m_TradingAccounts->push_back(ta);
		}
	}
}

void InvestorAccount::SafeUpdate( const SettlementInfo& si,bool bIsLast)
{
	boost::unique_lock<boost::mutex> lck(m_Mutex4SettlementInfo);
	Update(si,bIsLast);
}


void InvestorAccount::SafeUpdate(const SettlementInfoConfirm& sic, bool bIsLast /*= false*/)
{
	if (!m_SettlementInfo)
	{
		m_SettlementInfoConfirm = boost::make_shared<SettlementInfoConfirm>(sic);
	}
	else
	{
		*m_SettlementInfoConfirm = sic;
	}
}


void InvestorAccount::SafeUpdate(InvestorPositionDetailSPtr ipd,bool isUserLogin/*=false*/)
{
	boost::unique_lock<boost::mutex> lck(m_Mutex4PosDetail);
	Update(ipd);
}

void InvestorAccount::SafeUpdate(boost::shared_ptr<InvestorPositionCombineDetail> ipcd, bool bUserIsLogin /*= false*/)
{
	boost::unique_lock<boost::mutex> lck(m_Mutex4CmbPosDetail);
	Update(ipcd);
}

void InvestorAccount::SafeUpdate(InvestorPositionSPtr ip, bool bUserIsLogin /*= false*/)
{
	boost::unique_lock<boost::mutex> lck(m_Mutex4CmbPosDetail);
	Update(ip);
}

void InvestorAccount::SafeUpdate(TickSPtr tick)
{
	Portfolio::Update(tick);
}

void InvestorAccount::SafeUpdate(InputOrderSPtr pInputOrder)
{
	Portfolio::Update(pInputOrder);
}

void InvestorAccount::SafeUpdate(InputOrderActionSPtr pInputOrder)
{
	Portfolio::Update(pInputOrder);
}

void InvestorAccount::SafeUpdate(boost::shared_ptr<BrokerTradingParams> borkerTradingParam)
{
	m_BrokerTradingParams = borkerTradingParam;
}

void InvestorAccount::SafeUpdate(boost::shared_ptr<InstrumentCommisionRate> pRate, bool bUserIsLogin /*= false*/)
{
	m_InstCommisionRates[pRate->InstrumentID] = pRate;
}

void InvestorAccount::SafeUpdate(boost::shared_ptr<InstrumentMarginRate> pRate, bool bUserIsLogin /*= false*/)
{
	m_InstMarginRates[pRate->InstrumentID] = pRate;
}

boost::shared_ptr<InstrumentCommisionRate> InvestorAccount::GetInstCommissionRate(const std::string& instId)
{
	auto cIter = this->m_InstCommisionRates.find(instId);
	if (cIter==m_InstCommisionRates.end())
	{
		return nullptr;
	}
	return cIter->second;
}

boost::shared_ptr<InstrumentMarginRate> InvestorAccount::GetInstMarginRate(const std::string& instId)
{
	auto cIter = m_InstMarginRates.find(instId);
	if (cIter == m_InstMarginRates.end())
	{
		return nullptr;
	}
	return cIter->second;
}


void InvestorAccount::LoadInstCommisionRate()
{
	//加载手续费率;
	std::ifstream ifs("CTP_CommisionRate.bin", std::ios::binary);

	if (ifs.is_open())
	{
		boost::archive::binary_iarchive oa(ifs);

		oa >> m_InstCommisionRates;

		ifs.close();
	}
}

void InvestorAccount::SaveInstCommisionRate()
{
	if (m_InstCommisionRates.size() == 0)
	{
		return;
	}
	//保存报单信息;
	std::ofstream ofs("CTP_CommisionRate.bin", std::ios::binary);

	if (ofs.is_open())
	{
		boost::archive::binary_oarchive oa(ofs);

		oa << m_InstCommisionRates;

		ofs.close();
	}
}

void InvestorAccount::LoadInstMarginRate()
{
	std::ifstream ifs("CTP_MarginRate.bin", std::ios::binary);

	if (ifs.is_open())
	{
		boost::archive::binary_iarchive oa(ifs);

		oa >> m_InstMarginRates;

		ifs.close();
	}
}

void InvestorAccount::SaveInstMarginRate()
{
	if (m_InstMarginRates.size() == 0)
	{
		return;
	}
	//保存报单信息;
	std::ofstream ofs("CTP_MarginRate.bin", std::ios::binary);

	if (ofs.is_open())
	{
		boost::archive::binary_oarchive oa(ofs);

		oa << m_InstMarginRates;

		ofs.close();
	}
}






bool InvestorAccount::IsMyTrade(TradeSPtr trade)
{
	if (!trade)
	{
		return false;
	}
	//查找所有的Orders,匹配OrderSysID
	auto oditer = m_MyOrders->find(trade->OrderSysID);
	return oditer != m_MyOrders->end();

}

std::string InvestorAccount::GetField(int field)
{
	return std::string();
}

void InvestorAccount::setField(int field, const std::string & value)
{
}

std::pair<std::string,std::string> InvestorAccount::GetInvestorIDBrokerID()
{
	return std::pair<std::string,std::string>(m_Investor->InvestorID,m_Investor->BrokerID);
}


boost::shared_ptr<Investor> InvestorAccount::GetInvestor()
{
	boost::unique_lock<boost::mutex> lck(m_Mutex4Investor);
	return m_Investor;
}


boost::shared_ptr<SettlementInfo> InvestorAccount::GetSettlementInfo()
{
	boost::unique_lock<boost::mutex> lck(m_Mutex4SettlementInfo);
	return m_SettlementInfo;
}


std::vector<boost::shared_ptr<InvestorPositionDetail> >& InvestorAccount::GetInvestorPositionDetail()
{
	return m_InvestorPositionDetail;
}

std::vector<boost::shared_ptr<InvestorPositionCombineDetail>>& InvestorAccount::GetInvestorComboPositionsDetail()
{
	return m_InvestorPositionCombineDetail;
}

boost::shared_ptr<BrokerTradingParams> InvestorAccount::GetBrokerTradingParams()
{
	return m_BrokerTradingParams;
}

std::map<std::string, boost::shared_ptr<InstrumentCommisionRate> >& InvestorAccount::GetInstCommissionRates()
{
	return m_InstCommisionRates;
}

std::map<std::string, boost::shared_ptr<InstrumentMarginRate> >& InvestorAccount::GetInstMarginRates()
{
	return m_InstMarginRates;
}

boost::shared_ptr<SettlementInfoConfirm> InvestorAccount::GetSettlementInfoConfirm()
{
	return m_SettlementInfoConfirm;
}


void InvestorAccount::SetFilterMyOrder(bool bFilter)
{
	m_bFilterMyOrder = bFilter;
}

bool InvestorAccount::IsFilterMyOrder() const
{
	return m_bFilterMyOrder;
}

UserInfo& InvestorAccount::GetUser()
{
	return *this;
}


bool InvestorAccount::IsMyOrder(OrderSPtr order)
{
	if (order)
	{
		if (!IsFilterMyOrder())
		{
			if (BrokerID == order->BrokerID && UserID == order->UserID)
			{
				return true;
			}
		}
		else
		{
			if ((order->FrontID ==FrontID
				&& order->SessionID == SessionID))
			{
				return true;
			}
		}
	}
	return false;
}
